package liangtWorkSpace.bit;

/**
 * @ClassName BitMain
 * @Description : 功能说明
 * @Author : LiangT
 * @Date : 2020/4/16 17:18
 */

/**
 * 位运算
 */
public class BitMain {
    public static void main(String[] args) {
//        System.out.println(1&1);
//        System.out.println(1|3);
//        System.out.println(~0);
//        System.out.println();
//        bitMain();
        bitMain2();
    }

    /**
     * 操作规则：同为1则1，否则为0。
     * 仅当两个操作数都为1时，输出结果才为1，否则为0
     */
    public static void bitMain2() {
        int i = 0b100; //4
        int j = 0b101; //5
        int n = -0B100;

        /* & 运算符操作规则：同为1则1，否则为0。仅当两个操作数都为1时，输出结果才为1，否则为0*/
        System.out.println(Integer.toBinaryString(i & j));
        System.out.println(i & j);//4
        System.out.println(i & i);//4
        System.out.println(j & j);//5

        /* | 运算符 操作规则：**同为0则0，否则为1**。仅当两个操作数都为0时，输出的结果才为0。
         */
        System.out.println("********");
        System.out.println(j | i);
        System.out.println(j | j);
        System.out.println(i | i);

        /* ~ 操作符 操作规则：0为1，1为0。全部的0置为1，1置为0。
         * */
        System.out.println("********");
        System.out.println("二进制取反：" + Integer.toBinaryString(~i));
        System.out.println("-5二进制：" + Integer.toBinaryString(-5));
        System.out.println("最大整数二进制：" + Integer.toBinaryString(Integer.MAX_VALUE));
        System.out.println("最大整数二进制取反：" + Integer.toBinaryString(~Integer.MAX_VALUE));
        System.out.println("十进制取反：" + ~i);

        /* ^ 操作符 操作规则：相同为0，不同为1。操作数不同时（1遇上0，0遇上1）对应的输出结果才为1，否则为0 */
        System.out.println("*****************");
        System.out.println("二进制结果展示：" + Integer.toBinaryString(i ^ j));
        System.out.println("十进制结果展示：" + (i ^ j));

        /* << 左移运算符 向左移动N位，十进制相当于乘2的N次方*/
        System.out.println("***************");
        System.out.println("正整数左移：" + (i << 4));
        System.out.println("负数左移" + (n << 4));
        /* >> 右移运算符 向右移动N位， 十进制相当于除2的N次方 */
        System.out.println("***************");
        System.out.println("正数右移" + (i >> 2));
        System.out.println("负数右移" + (n >> 2));
        /* >>> 无符号右移 它和>>有符号右移的区别是：无论是正数还是负数，高位通通补0。所以说对于正数而言，没有区别；那么看看对于负数的表现*/
        System.out.println("******");
        System.out.println("正数无符号右移：" + (i >>> 2));
        System.out.println("负数无符号右移：" + (n >>> 2));

        /*判断两个数字字符是否相同*/
        System.out.println("***********");
        int s = 100;
        int x = -2;
        //false 前后不等 ^亦或 两者相同则为0 不通则为1,位移31位之后只有符号位未改变
        System.out.println(((s >> 31) ^ (x >> 31)) == 0);
        x = 10;
        System.out.println(((s >> 31) ^ (x >> 31)) == 0);

        /*判断一个数的奇偶*/
        System.out.println("************");
        System.out.println(isEvenNum(1));
        System.out.println(isEvenNum(2));

        /* 交换两个数 */
        System.out.println("**********");
        swap(i, j);
        swapBit(i,j);
        System.out.println(i + " ******* " + j);
    }

    /**
     * 判断一个数的奇偶
     * 为何&1能判断基偶性？因为在二进制下偶数的末位肯定是0，奇数的最低位肯定是1。
     * 而二进制的1它的前31位均为0，所以在和其它数字的前31位与运算后肯定所有位数都是0（无论是1&0还是0&0结果都是0），那么唯一区别就是看最低位和1进行与运算的结果喽：结果为1表示奇数，反则结果为0就表示偶数
     *
     * @param number
     * @return
     */
    public static boolean isEvenNum(int number) {
        return (number & 1) == 0;
    }

    /**
     * 交换两个数
     * 使用这种方式最大的好处是：容易理解。最大的坏处是：a+b,可能会超出int型的最大范围，造成精度丢失导致错误，造成非常隐蔽的bug。所以若你这样运用在生产环境的话，是有比较大的安全隐患的
     *
     * @param a
     * @param b
     */
    public static void swap(int a, int b) {
        a = a + b;
        b = a - b;
        a = a - b;
        System.out.println(a + " ******* " + b);
    }

    /**
     * 位运算交换两个值
     * 位运算的可逆性，使用异或来达成目的
     * @param a
     * @param b
     */
    public static void swapBit(int a, int b) {
        a = a ^ b;
        b = a ^ b;
        a = a ^ b;
        System.out.println(a + " ******* " + b);
    }

    public static void bitMain() {
        System.out.println(6 & 3);
        System.out.println(6 | 3);
        System.out.println(6 ^ 3);
        System.out.println(~6);
        System.out.println(3 << 2);
        System.out.println(3 >> 1);
        System.out.println(3 >>> 1);
    }


}
